package com.youxin.admin.auth.service.Impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youxin.admin.auth.domain.AuthorityMenuTree;
import com.youxin.admin.auth.domain.RoleDto;
import com.youxin.admin.auth.domain.RoleUser;
import com.youxin.admin.auth.enums.AdminCommonConstant;
import com.youxin.admin.auth.mapper.MenuMapper;
import com.youxin.admin.auth.mapper.ResourceAuthorityMapper;
import com.youxin.admin.auth.mapper.RoleMapper;
import com.youxin.admin.auth.mapper.UserMapper;
import com.youxin.admin.auth.model.Menu;
import com.youxin.admin.auth.model.ResourceAuthority;
import com.youxin.admin.auth.model.Role;
import com.youxin.admin.auth.service.ChatRoleService;
import com.youxin.admin.auth.service.ResourceAuthorityService;
import com.youxin.base.TPage;
import com.youxin.exception.SystemException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ChatRoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements ChatRoleService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private ResourceAuthorityMapper resourceAuthorityMapper;


    public IPage<Role> selectPage(Page<Role> page, Wrapper<Role> wrapper) {
        return this.baseMapper.selectPage(page, wrapper);
    }

    public List<Role> selectList(Wrapper<Role> wrapper) {
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public IPage<Role> selectPage(IPage<Role> page, QueryWrapper<Role> wrapper) throws SystemException {
        return this.baseMapper.selectPage(page, wrapper);
    }

    @Override
    public List<Role> selectList(QueryWrapper<Role> wrapper) throws SystemException {
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public void modifyRoleUsers(int roleId, Integer userId, Integer action) throws SystemException {

        if (action == 0) {
            this.baseMapper.deleteRoleMembersById(roleId, userId);
        } else {
            this.baseMapper.insertRoleMembersById(roleId, userId);

        }
    }

    @Override
    public TPage<List<RoleUser>> getRoleUsers(int roleId, String username, int currentPage, int showCount) throws SystemException {
        if (!StringUtils.isEmpty(username)) {
            username = "%" + username + "%";
        }
        IPage page = userMapper.selectMemberByRoleId(new Page<>(currentPage, showCount), roleId, username);
        return TPage.page(page.getRecords(), page.getTotal());
    }

    @Override
    public void modifyAuthorityMenu(int roleId, String[] menus) throws SystemException {
        resourceAuthorityMapper.deleteRoleMemberByRoleId(roleId);
        List<Menu> menuList = menuMapper.selectList(new LambdaQueryWrapper<>());
        Map<String, String> map = new HashMap<String, String>();
        for (Menu menu : menuList) {
            map.put(menu.getId().toString(), menu.getParentId().toString());
        }
        Set<String> relationMenus = new HashSet<String>();
        relationMenus.addAll(Arrays.asList(menus));
        ResourceAuthority authority = null;
        for (String menuId : menus) {
            findParentID(map, relationMenus, menuId);
        }
        for (String menuId : relationMenus) {
            authority = new ResourceAuthority();
            authority.setAuthorityId(roleId);
            authority.setResourceId(Integer.parseInt(menuId));
            authority.setParentId(-1);
            resourceAuthorityMapper.insert(authority);
        }
    }

    private void findParentID(Map<String, String> map, Set<String> relationMenus, String id) {
        String parentId = map.get(id);
        if (String.valueOf(AdminCommonConstant.ROOT).equals(id)) {
            return;
        }
        relationMenus.add(parentId);
        findParentID(map, relationMenus, parentId);
    }

    @Override
    public List<AuthorityMenuTree> getAuthorityMenu(int roleId) throws SystemException {
        List<Menu> menus = menuMapper.selectMenuByAuthorityId(String.valueOf(roleId));
        List<AuthorityMenuTree> trees = new ArrayList<AuthorityMenuTree>();
        AuthorityMenuTree node = null;
        for (Menu menu : menus) {
            node = new AuthorityMenuTree();
            node.setText(menu.getTitle());
            BeanUtils.copyProperties(menu, node);
            trees.add(node);
        }
        return trees;
    }

    @Override
    public void modifyAuthorityElement(int roleId, int menuId, int elementId) throws SystemException {
        ResourceAuthority authority = new ResourceAuthority();
        authority.setAuthorityId(roleId);
        authority.setResourceId(elementId);
        authority.setParentId(-1);
        QueryWrapper<ResourceAuthority> condition = new QueryWrapper<>();
        condition.eq("authority_id", roleId + "");
        condition.eq("resource_id", elementId + "");
        condition.eq("parent_id", menuId);
        resourceAuthorityMapper.delete(condition);
        resourceAuthorityMapper.insert(authority);
    }

    @Override
    public void removeAuthorityElement(int groupId, int menuId, int elementId) throws SystemException {

        QueryWrapper<ResourceAuthority> condition = new QueryWrapper<>();
        condition.eq("authority_id", groupId + "");
        condition.eq("resource_id", elementId + "");
        condition.eq("parent_id", menuId);

        resourceAuthorityMapper.delete(condition);
    }

    @Override
    public void batchModifyAuthorityElement(int roleId, int menuId, List<Integer> elementIds) throws SystemException {
        QueryWrapper<ResourceAuthority> condition = new QueryWrapper<>();
        condition.eq("authority_id", roleId + "");
        condition.eq("resource_id", menuId);
//        condition.eq("resource_type", AdminCommonConstant.RESOURCE_TYPE_BTN);
        resourceAuthorityMapper.delete(condition);
        List<ResourceAuthority> list = elementIds.stream().filter(elementId -> (elementId != null)).map(elementId -> {
            ResourceAuthority authority = new ResourceAuthority();
            authority.setAuthorityId(roleId);
            authority.setResourceId(elementId);
//            authority.setParentId(menuId+"");
            return authority;
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(list)) {
            resourceAuthorityMapper.insertBatch(list);
        }
    }

    @Override
    public void batchRemoveElementAuthority(int roleId, int menuId, List<Integer> elementIds) throws SystemException {
        QueryWrapper<ResourceAuthority> condition = new QueryWrapper<>();
        condition.eq("authority_id", roleId + "");
        condition.in("resource_id", elementIds);
        condition.eq("parent_id", -1);
        resourceAuthorityMapper.delete(condition);
    }

    @Override
    public List<Integer> getAuthorityElement(int groupId) throws SystemException {
        ResourceAuthority authority = new ResourceAuthority();
        authority.setAuthorityId(groupId);
        QueryWrapper<ResourceAuthority> condition = new QueryWrapper<>();
        condition.eq("authority_id",groupId);
        List<ResourceAuthority> authorities = resourceAuthorityMapper.selectList(condition);
        List<Integer> ids = new ArrayList<Integer>();
        for (ResourceAuthority auth : authorities) {
            ids.add(auth.getResourceId());
        }
        return ids;
    }

    @Override
    public boolean insert(Role role) throws SystemException {
      return this.baseMapper.insert(role) > 0;
    }

    @Override
    public Role selectById(Integer id) throws SystemException {
        return this.baseMapper.selectById(id);
    }

    @Override
    public int deleteById(Integer id) throws SystemException {
        return this.baseMapper.deleteById(id);
    }

    @Override
    public void updateById(RoleDto roleDto) throws SystemException {
        resourceAuthorityMapper.deleteRoleMemberByRoleId(roleDto.getId());
        if (!CollectionUtils.isEmpty(roleDto.getMenuIds())) {
            resourceAuthorityMapper.insertRoleMember(roleDto.getMenuIds(), roleDto.getId(), roleDto.getUpdateBy());
        }
        Role role = new Role();
        role.setId(roleDto.getId());
        role.setName(roleDto.getName());
        role.setDescription(roleDto.getDescription());
        role.setUpdateBy(roleDto.getUpdateBy());
        role.setUpdateTime(new Date());
        this.baseMapper.updateById(role);    }


}
